
#include <stdio.h>
#include <string.h>
#include "ReadFile.h"
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "OCIDriver\FMDBApplication.h"
#include "OCIDriver\FMConnection.h"
#include "OCIDriver\FMDBCommand.h"

int main(int argc, char* argv[], char* envp[])
{
	time_t StartTime;
	time(&StartTime);
	//analyze arguments			
	char* pFile=NULL;
	char* pConnStr=NULL;
	int CacheSize=1000;

	for (int i=1;i<argc;i++)
	{
		if(strncmp(argv[i],"file=",5)==0)
		{
			pFile=argv[i]+5;
			continue;
		}
		if(strncmp(argv[i],"user=",5)==0)//format must be: "user/password@host:port/service\0"
		{
			pConnStr=argv[i]+5;
			continue;
		}
		if(strncmp(argv[i],"cache=",6)==0)//cache size
		{
			char *pCache=argv[i]+6;
			CacheSize=atoi(pCache);
			if (CacheSize<1)
			{
				CacheSize=1;
			}
			continue;
		}
	}

	//these two arguments cannot be null
	if (pFile==NULL || pConnStr==NULL)
	{
		printf("arguments file= user= must set\n");
		return -1;
	}



	//open input file
	FILE *pf=NULL;
	pf=fopen(pFile,"r");

	if (!pf)
	{
		printf("cannot open file:%s \n",pFile);
		return -1;
	}

	//todo:get connection string from argument
	char* strConString="//10.86.0.14:1521/fmorcl";
	char* strUserName="fmuser_jwh";
	char* strPsw="futurmaster";

	//open DB	
	FMDBApplication& oraDB = FMDBApplication::GetInstance();
	oraDB.SetConnectionString(strConString);
	oraDB.SetUserName(strUserName);
	oraDB.SetPassword(strPsw);

	//open db
	oraDB.OpenDB ();

	//get data
	FMDBConnection conn(&oraDB);
	conn.Open();
	FMDBCommand cmd(&conn);
	char* strSQL="insert into TBMID141005(AGGNODE,PRODUCT , SALES , TRADE , ENDDATE, T_1 , T_2 , T_3 , T_4 , T_5 , T_6 , T_7 , T_8 , T_9 , T_10 , T_11 , T_12 , T_13 , T_14 , T_15 , T_16 , T_17 , T_18 , T_19 , T_20 , T_21 , T_22 , T_23 , T_24 , T_25 , T_26 , T_27 , T_28 , T_29 , T_30 , T_31 , T_32 , T_33 , T_34 , T_35 , T_36 , T_37 , T_38 , T_39 , T_40 , T_41 , T_42 , T_43 , T_44 , T_45 , T_46 , T_47 , T_48 , T_49 , T_50 , T_51 , T_52 , T_53 , T_54 , T_55 , T_56 , T_57 , T_58 , T_59 , T_60 , T_61 , T_62 , T_63 , T_64 , T_65 , T_66 , T_67 , T_68 , T_69 , T_70 , T_71 , T_72 , T_73 , T_74 , T_75 , T_76 , T_77 , T_78 , T_79 , T_80 , T_81 , T_82 , T_83 , T_84 , T_85 , T_86 , T_87 , T_88 , T_89 , T_90 , T_91 , T_92 , T_93 , T_94 , T_95 , T_96 , T_97 , T_98 , T_99 , T_100 , T_101 , T_102 , T_103 , T_104 , T_105 , T_106 , T_107 , T_108 , T_109 , T_110 , T_111 , T_112 , T_113 , T_114 , T_115 , T_116 , T_117 , T_118 , T_119 , T_120 , T_121 , T_122 , T_123 , T_124 , T_125 , T_126 , T_127 , T_128 , T_129 , T_130 , T_131 , T_132 , T_133 , T_134 , T_135 , T_136 , T_137 , T_138 , T_139 , T_140 , T_141 , T_142 , T_143 , T_144 , T_145 , T_146 , T_147 , T_148 , T_149 , T_150 , T_151 , T_152 , T_153 , T_154 , T_155 , T_156 , T_157 , T_158 , T_159 , T_160 , T_161 , T_162 , T_163 , T_164 , T_165 , T_166 , T_167 , T_168 , T_169 , T_170 , T_171 , T_172 , T_173 , T_174 , T_175 , T_176 , T_177 , T_178 , T_179 , T_180 , T_181 , T_182 , T_183 , T_184 , T_185 , T_186 , T_187 , T_188 , T_189 , T_190 , T_191 , T_192)\
	values (:AGGNODE,:PRODUCT , :SALES , :TRADE , :ENDDATE, :T_1 , :T_2 , :T_3 , :T_4 , :T_5 , :T_6 , :T_7 , :T_8 , :T_9 , :T_10 , :T_11 , :T_12 , :T_13 , :T_14 , :T_15 , :T_16 , :T_17 , :T_18 , :T_19 , :T_20 , :T_21 , :T_22 , :T_23 , :T_24 , :T_25 , :T_26 , :T_27 , :T_28 , :T_29 , :T_30 , :T_31 , :T_32 , :T_33 , :T_34 , :T_35 , :T_36 , :T_37 , :T_38 , :T_39 , :T_40 , :T_41 , :T_42 , :T_43 , :T_44 , :T_45 , :T_46 , :T_47 , :T_48 , :T_49 , :T_50 , :T_51 , :T_52 , :T_53 , :T_54 , :T_55 , :T_56 , :T_57 , :T_58 , :T_59 , :T_60 , :T_61 , :T_62 , :T_63 , :T_64 , :T_65 , :T_66 , :T_67 , :T_68 , :T_69 , :T_70 , :T_71 , :T_72 , :T_73 , :T_74 , :T_75 , :T_76 , :T_77 , :T_78 , :T_79 , :T_80 , :T_81 , :T_82 , :T_83 , :T_84 , :T_85 , :T_86 , :T_87 , :T_88 , :T_89 , :T_90 , :T_91 , :T_92 , :T_93 , :T_94 , :T_95 , :T_96 , :T_97 , :T_98 , :T_99 , :T_100 , :T_101 , :T_102 , :T_103 , :T_104 , :T_105 , :T_106 , :T_107 , :T_108 , :T_109 , :T_110 , :T_111 , :T_112 , :T_113 , :T_114 , :T_115 , :T_116 , :T_117 , :T_118 , :T_119 , :T_120 , :T_121 , :T_122 , :T_123 , :T_124 , :T_125 , :T_126 , :T_127 , :T_128 , :T_129 , :T_130 , :T_131 , :T_132 , :T_133 , :T_134 , :T_135 , :T_136 , :T_137 , :T_138 , :T_139 , :T_140 , :T_141 , :T_142 , :T_143 , :T_144 , :T_145 , :T_146 , :T_147 , :T_148 , :T_149 , :T_150 , :T_151 , :T_152 , :T_153 , :T_154 , :T_155 , :T_156 , :T_157 , :T_158 , :T_159 , :T_160 , :T_161 , :T_162 , :T_163 , :T_164 , :T_165 , :T_166 , :T_167 , :T_168 , :T_169 , :T_170 , :T_171 , :T_172 , :T_173 , :T_174 , :T_175 , :T_176 , :T_177 , :T_178 , :T_179 , :T_180 , :T_181 , :T_182 , :T_183 , :T_184 , :T_185 , :T_186 , :T_187 , :T_188 , :T_189 , :T_190 , :T_191 , :T_192)";
	//char* strSQL="insert into TBMID141005(AGGNODE,PRODUCT , SALES , TRADE, ENDDATE ) values (:AGGNODE,:PRODUCT , :SALES , :TRADE, :ENDDATE)";

	cmd.SetSQLStatement(strSQL);


	//begin----------------todo: here I uses fixed column number and type,next step,uses control file------------
	const int FieldLengthAGGNODE=202;
	const int FieldLengthPRODUCT=62;
	const int FieldLengthSALES=62;
	const int FieldLengthTRADE=62;
	const int FieldLengthENDDATE=16;
	const int FieldsCount=197;

	//prepare data from file
	char *AGGNODE=(char*)malloc(CacheSize*FieldLengthAGGNODE);
	char *PRODUCT=(char*)malloc(CacheSize*FieldLengthPRODUCT);
	char *SALES=(char*)malloc(CacheSize*FieldLengthSALES);
	char *TRADE=(char*)malloc(CacheSize*FieldLengthTRADE);
	char *ENDDATE=(char*)malloc(CacheSize*FieldLengthENDDATE);
	double*pTx=(double*)malloc(CacheSize*192*sizeof(double));
	short *pIndTx=(short*)malloc(CacheSize*192*sizeof(short));

	/*typedef char* charp;
	charp Pos[197];*/

	
	char *Pos[197];//each address of ',' or the end position of fields

	memset(AGGNODE,0,CacheSize*FieldLengthAGGNODE);
	memset(PRODUCT,0,CacheSize*FieldLengthPRODUCT);
	memset(TRADE,0,CacheSize*FieldLengthSALES);
	memset(SALES,0,CacheSize*FieldLengthTRADE);
	memset(ENDDATE,0,CacheSize*FieldLengthENDDATE);
	
	char *colName[197]={":AGGNODE",":PRODUCT",":SALES",":TRADE",":ENDDATE",":T_1",":T_2",":T_3",":T_4",":T_5",":T_6",":T_7",":T_8",":T_9",":T_10",":T_11",":T_12",":T_13",":T_14",":T_15",":T_16",":T_17",":T_18",":T_19",":T_20",":T_21",":T_22",":T_23",":T_24",":T_25",":T_26",":T_27",":T_28",":T_29",":T_30",":T_31",":T_32",":T_33",":T_34",":T_35",":T_36",":T_37",":T_38",":T_39",":T_40",":T_41",":T_42",":T_43",":T_44",":T_45",":T_46",":T_47",":T_48",":T_49",":T_50",":T_51",":T_52",":T_53",":T_54",":T_55",":T_56",":T_57",":T_58",":T_59",":T_60",":T_61",":T_62",":T_63",":T_64",":T_65",":T_66",":T_67",":T_68",":T_69",":T_70",":T_71",":T_72",":T_73",":T_74",":T_75",":T_76",":T_77",":T_78",":T_79",":T_80",":T_81",":T_82",":T_83",":T_84",":T_85",":T_86",":T_87",":T_88",":T_89",":T_90",":T_91",":T_92",":T_93",":T_94",":T_95",":T_96",":T_97",":T_98",":T_99",":T_100",":T_101",":T_102",":T_103",":T_104",":T_105",":T_106",":T_107",":T_108",":T_109",":T_110",":T_111",":T_112",":T_113",":T_114",":T_115",":T_116",":T_117",":T_118",":T_119",":T_120",":T_121",":T_122",":T_123",":T_124",":T_125",":T_126",":T_127",":T_128",":T_129",":T_130",":T_131",":T_132",":T_133",":T_134",":T_135",":T_136",":T_137",":T_138",":T_139",":T_140",":T_141",":T_142",":T_143",":T_144",":T_145",":T_146",":T_147",":T_148",":T_149",":T_150",":T_151",":T_152",":T_153",":T_154",":T_155",":T_156",":T_157",":T_158",":T_159",":T_160",":T_161",":T_162",":T_163",":T_164",":T_165",":T_166",":T_167",":T_168",":T_169",":T_170",":T_171",":T_172",":T_173",":T_174",":T_175",":T_176",":T_177",":T_178",":T_179",":T_180",":T_181",":T_182",":T_183",":T_184",":T_185",":T_186",":T_187",":T_188",":T_189",":T_190",":T_191",":T_192"};
	//end----------------todo: here I uses fixed column number and type,next step,uses control file------------


	//read from file and fill the buffer
	char* pStart=NULL;
	int iCurRow=0;
	long iRowsTotal=0;
	int LineBufferSize=2000;
	char *LineBuffer=new char[LineBufferSize];//one line string
	int fieldsTmp=0;//current position of fields in one line string buffer
	char pDoubleTmp[100];
	double dValue=0;

	while(fgets(LineBuffer,LineBufferSize,pf)!=NULL)
	{
		iRowsTotal++;
		pStart=LineBuffer;
		fieldsTmp=0;
		//get all position of ',' in this line buffer
		while (*pStart!='\0')
		{
			if (*pStart==',')
			{
				Pos[fieldsTmp]=pStart;
				fieldsTmp++;
			}
			pStart++;
		} ;

		assert(fieldsTmp==FieldsCount);//fail means wrong format of file

		memcpy_s(AGGNODE+iCurRow*FieldLengthAGGNODE,Pos[0]-LineBuffer,LineBuffer,Pos[0]-LineBuffer);
		memcpy_s(PRODUCT+iCurRow*FieldLengthPRODUCT,Pos[1]-Pos[0]-1,Pos[0]+1,Pos[1]-Pos[0]-1);
		memcpy_s(SALES+iCurRow*FieldLengthSALES,Pos[2]-Pos[1]-1,Pos[1]+1,Pos[2]-Pos[1]-1);
		memcpy_s(TRADE+iCurRow*FieldLengthTRADE,Pos[3]-Pos[2]-1,Pos[2]+1,Pos[3]-Pos[2]-1);
		memcpy_s(ENDDATE+iCurRow*FieldLengthENDDATE,Pos[4]-Pos[3]-1,Pos[3]+1,Pos[4]-Pos[3]-1);
		
		//get rest 192 columns with double value
		for (int i=5;i<FieldsCount;i++)
		{
			if (Pos[i]==Pos[i-1]+1)//null value
			{
				pIndTx[iCurRow+(i-5)*CacheSize]=-1;
			} 
			else
			{
				memset(pDoubleTmp,0,100);
				memcpy_s(pDoubleTmp,Pos[i]-Pos[i-1]-1,Pos[i-1]+1,Pos[i]-Pos[i-1]-1);
				dValue=atof(pDoubleTmp);
				pTx[iCurRow+(i-5)*CacheSize]=dValue;
				pIndTx[iCurRow+(i-5)*CacheSize]=0;
			}

		}
		iCurRow++;

		//cache full
		if (iCurRow==CacheSize)
		{
			//commit cache to db
			FMDBParameters Params;

			FMDBParameter paramAGGNODE(colName[0],AGGNODE);
			paramAGGNODE.SetVarSize(FieldLengthAGGNODE);
			Params.AddParam(&paramAGGNODE);

			FMDBParameter paramPRODUCT(colName[1],PRODUCT);
			paramPRODUCT.SetVarSize(FieldLengthPRODUCT);
			Params.AddParam(&paramPRODUCT);

			FMDBParameter paramSALES(colName[2],SALES);
			paramSALES.SetVarSize(FieldLengthSALES);
			Params.AddParam(&paramSALES);

			FMDBParameter paramTRADE(colName[3],TRADE);
			paramTRADE.SetVarSize(FieldLengthTRADE);
			Params.AddParam(&paramTRADE);

			FMDBParameter paramENDDATE(colName[4],ENDDATE);
			paramENDDATE.SetVarSize(FieldLengthENDDATE);
			Params.AddParam(&paramENDDATE);

			FMDBParameter T[192];
			
			for (int i=0;i<192;i++)
			{

				T[i].Set(colName[i+5],&pTx[i]);
				T[i].SetIndicator(&pIndTx[i]);
				T[i].SetVarSize(sizeof(double));
				Params.AddParam(&T[i]);
			}
					

			//commit
			cmd.SetParameters(&Params,CacheSize);//note:here must set cache size=array size
			//execute command
			cmd.ExecuteSQLNoQuery(strSQL,&Params,EXECUTION_MODE_COMMIT_ON_SUCCESS);
					
			//printf("insert %d\n",iRowsTotal);

			//clear memory
			memset(AGGNODE,0,CacheSize*FieldLengthAGGNODE);
			memset(PRODUCT,0,CacheSize*FieldLengthPRODUCT);
			memset(TRADE,0,CacheSize*FieldLengthSALES);
			memset(SALES,0,CacheSize*FieldLengthTRADE);
			memset(ENDDATE,0,CacheSize*FieldLengthENDDATE);
			iCurRow=0;
		}
	}

	//commit remaining cache
		if (iCurRow>0)
		{
			//commit cache to db
			FMDBParameters Params;

			FMDBParameter paramAGGNODE(colName[0],AGGNODE);
			paramAGGNODE.SetVarSize(FieldLengthAGGNODE);
			Params.AddParam(&paramAGGNODE);

			FMDBParameter paramPRODUCT(colName[1],PRODUCT);
			paramPRODUCT.SetVarSize(FieldLengthPRODUCT);
			Params.AddParam(&paramPRODUCT);

			FMDBParameter paramSALES(colName[2],SALES);
			paramSALES.SetVarSize(FieldLengthSALES);
			Params.AddParam(&paramSALES);

			FMDBParameter paramTRADE(colName[3],TRADE);
			paramTRADE.SetVarSize(FieldLengthTRADE);
			Params.AddParam(&paramTRADE);

			FMDBParameter paramENDDATE(colName[4],ENDDATE);
			paramENDDATE.SetVarSize(FieldLengthENDDATE);
			Params.AddParam(&paramENDDATE);

			FMDBParameter T[192];

			for (int i=0;i<192;i++)
			{

				T[i].Set(colName[i+5],&pTx[i]);
				T[i].SetIndicator(&pIndTx[i]);
				T[i].SetVarSize(sizeof(double));
				Params.AddParam(&T[i]);
			}
					

			//commit
			cmd.SetParameters(&Params,iCurRow);//note:here must set cache size=array size
			//execute command
			cmd.ExecuteSQLNoQuery(strSQL,&Params,EXECUTION_MODE_COMMIT_ON_SUCCESS);
					
			//printf("insert %d\n",iRowsTotal);
		}

	time_t EndTime;
	time(&EndTime);
	printf("total rows insert:%d\n",iRowsTotal);
	printf("running time:%ds\n",EndTime-StartTime);

	//getchar();
	return 0;
}


